package com.nulldev.util.security.encryptAPI.impls.blowfish;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import com.nulldev.util.data.Variables;
import com.nulldev.util.data.Base64.Base64;
import com.nulldev.util.security.encryptAPI.Encryptor;

public class Blowfish extends Encryptor {

	public Blowfish(final String key) {
		this(key.getBytes());
	}

	public Blowfish(final byte[] key) {
		super("encryptapi.java.blowfish", new String[]
			{ "Blowfish" }, key);
		try {
			Cipher.getInstance("Blowfish");
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	}

	@Override
	public byte[] encryptToBytes(Object o) {
		Variables.notNullE(o);
		try {
			final Cipher e = Cipher.getInstance("Blowfish");
			e.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(this.key, "Blowfish"));
			if (o instanceof byte[]) {
				return e.doFinal((byte[]) o);
			} else if (o instanceof String) {
				return e.doFinal(((String) o).getBytes());
			} else {
				throw new UnsupportedOperationException("encrypt() -> Unsupported operation on: " + o);
			}
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	}

	@Override
	public String encrypt(Object o) {
		Variables.notNullE(o);
		try {
			final Cipher e = Cipher.getInstance("Blowfish");
			e.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(this.key, "Blowfish"));
			if (o instanceof byte[]) {
				return Base64.encodeBase64String(e.doFinal((byte[]) o));
			} else if (o instanceof String) {
				return Base64.encodeBase64String(e.doFinal(((String) o).getBytes()));
			} else {
				throw new UnsupportedOperationException("encrypt() -> Unsupported operation on: " + o);
			}
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	}

	@Override
	public String decrypt(final String s) {
		Variables.notNullE(s);
		try {
			final Cipher e = Cipher.getInstance("Blowfish");
			e.init(Cipher.DECRYPT_MODE, new SecretKeySpec(this.key, "Blowfish"));
			return new String(e.doFinal(Base64.decodeBase64(s)));
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	}

	@Override
	public byte[] decryptToBytes(final byte[] b) {
		Variables.notNullE(b);
		try {
			final Cipher e = Cipher.getInstance("Blowfish");
			e.init(Cipher.DECRYPT_MODE, new SecretKeySpec(this.key, "Blowfish"));
			return e.doFinal(b);
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	}

	@Override
	public byte[] getKey() {
		return this.key;
	}

	@Override
	public String getKeyAsString() {
		return Base64.encodeBase64String(this.key);
	}

}
